﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;

namespace KinectAPI
{
    public class BodyGestureGenerator
    {
        #region Fields

        string pluginPath = @"..\..\..\KinectAPI.Gestures.NDollar\bin\Debug";
        //string pluginPath = @"..\..\plugins";

        Dictionary<string, Gesture> gestures;

        Object[] argsGesture;

        #endregion

        #region Events

        public delegate void GestureStartHandler(string gesture, Object[] args);
        public event GestureStartHandler Start;

        public delegate void GestureEndHandler(string gesture, Object[] args);
        public event GestureEndHandler End;

        public delegate void GestureRecognisedHandler(string gesture, Object[] args);
        public event GestureRecognisedHandler Recognised;

        #endregion

        #region Constructor

        public BodyGestureGenerator(BodyTracker body)
        {
            gestures = new Dictionary<string, Gesture>();
            argsGesture = new Object[]{body, this, null};
        }

        #endregion

        #region Public Methods

        public void Add(string gestureName)
        {
            Add(gestureName, null);
        }

        public void Add(string gestureName, Object[] args)
        {
            if (String.IsNullOrEmpty(pluginPath)) 
            {
                throw new NotImplementedException();
            } //sanity check

            DirectoryInfo info = new DirectoryInfo(pluginPath);
            if (!info.Exists)
            {
                throw new NotImplementedException();
            } //make sure directory exists

            foreach (FileInfo file in info.GetFiles("*.dll")) //loop through all dll files in directory
            {
                //using Reflection, load Assembly into memory from disk
                Assembly currentAssembly = Assembly.LoadFile(file.FullName);

                System.Console.WriteLine("Found file " + file.FullName);

                //Type discovery to find the type we're looking for which is Gesture
                foreach (Type type in currentAssembly.GetTypes())
                {

                    if (!type.GetInterfaces().Contains(typeof(Gesture)))
                    {
                        continue;
                    }

                    Gesture gesture = (Gesture)Activator.CreateInstance(type);
                    if (gesture.getName().CompareTo(gestureName) == 0)
                    {
                        System.Console.WriteLine("add " + gestureName);
                        argsGesture[2] = args;
                        gesture.construct(argsGesture);
                        gesture.Recognised += new EventHandler(gesture_Recognised);
                        gesture.Start += new EventHandler(gesture_Start);
                        gesture.End += new EventHandler(gesture_End);
                        gestures.Add(gestureName, gesture);
                    }
                    else
                    {
                        System.Console.WriteLine("skip " + gesture.getName());
                    }
                }
            }
        }

        void gesture_Recognised(object sender, EventArgs e)
        {
            GestureEventArgs args = (GestureEventArgs)e;
            Recognised(args.gestureName, args.gestureArgs);
        }

        void gesture_Start(object sender, EventArgs e)
        {
            GestureEventArgs args = (GestureEventArgs)e;
            Start(args.gestureName, args.gestureArgs);
        }

        void gesture_End(object sender, EventArgs e)
        {
            GestureEventArgs args = (GestureEventArgs)e;
            End(args.gestureName, args.gestureArgs);
        }

        public void Remove(string gesture)
        {
            gestures.Remove(gesture);
        }

        #endregion
    }
}
